package gui;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import mvc.enhancedElicoide.ModelComplexHelix;
import mvc.model.ModelCurve;

public class ControlsPanel extends JFrame 
							{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private ModelComplexHelix model;
		
	public ControlsPanel(ModelComplexHelix model) {
		super("Controls");

		this.model = model;
		init();

	}


	private void init() {

		JPanel body = new JPanel();
		add(body); // Java JPanel delirium
		
		JPanel p1 = new JPanel();
		p1.setLayout(new GridLayout(10,1, 5, 5));
	    body.add(p1);
		
	    SliderPanel p = new SliderPanel("Point rate", 0, 800, 240, 
	    		model.getComplexHelix(), "Length");
	    p1.add(p);

	    p = new SliderPanel("Zoom factor", 0, 100, 20, 
				model.getComplexHelix(), "Zoom");
	    p1.add(p);
	    
		p = new SliderPanel("Elicoide Radius", 0, 80, 40, 
										model.getElicoideModel(), "R");
	    p1.add(p);
	    
	    p = new SliderPanel("Elicoide K", 0, 100, 30,
	    					model.getElicoideModel(), "K");
	    p1.add(p);
	    
	    p = new SliderPanel("Final curve U", 0, 100, 30,
				model.getComplexHelix(), "U");
	    p1.add(p);
	    
	    CheckboxPanel c = new CheckboxPanel("Trunk visibility",
	    		model.getComplexHelix(), "TrunkVisibility");
	    p1.add(c);
	}
	
	
	class CheckboxPanel extends JPanel implements ItemListener {

		private static final long serialVersionUID = 1L;
		private Object context;
		private String methodName;

		public CheckboxPanel(String label, ModelCurve context,
				String methodName) {
			
			this.context = context;
			this.methodName = methodName;
			
			setBorder(BorderFactory.createLineBorder(Color.black));
		    JCheckBox c = new JCheckBox(label);
		    add(c);
		    c.setSelected(true);
		    c.addItemListener(this);
		}

		@Override
		public void itemStateChanged(ItemEvent e) {
		    	
	    	try {
		
//		    		for(Method m : context.getClass().getMethods()){
//		    			System.out.println(m.toString());
//		    		}
	    		
//					Method getMethod = context.getClass().getMethod("get".concat(methodName));
//					Float oldValue = (Float) getMethod.invoke(context);
	    		
	    		Class<?>[] params = {boolean.class};
				Method setMethod = context.getClass().getMethod("set".concat(methodName), params);
				if(e.getStateChange()==ItemEvent.DESELECTED)
					setMethod.invoke(context,false);
				else setMethod.invoke(context,true);
				//model.notifyAllViews();
				model.getElicoideModel().notifyAllViews();
				model.getTrunkModel().notifyAllViews();
				
			} catch (SecurityException e1) {
				e1.printStackTrace();
			} catch (NoSuchMethodException e1) {
				e1.printStackTrace();
			}catch (IllegalArgumentException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (InvocationTargetException e1) {
				e1.printStackTrace();
			}
		}

		

		
	}
	
	
	class SliderPanel extends JPanel implements ChangeListener {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private Object context;
		private String methodName;

		SliderPanel(String label, int min, int max, int init,
				Object o, String m) {
			
			this.context = o;
			this.methodName = m;
			
			setBorder(BorderFactory.createLineBorder(Color.black));
		    add(new Label(label));
		    JSlider slider = new JSlider(min, max, init);
		    add(slider);
		    slider.setPaintTicks(true);
		    slider.setPaintLabels(true);
		    slider.addChangeListener(this);
		    
		}
		
		public void stateChanged(ChangeEvent e) {
		    JSlider source = (JSlider)e.getSource();
		    //if (!source.getValueIsAdjusting()) {
		    	
		    	try {
			
//		    		for(Method m : context.getClass().getMethods()){
//		    			System.out.println(m.toString());
//		    		}
		    		
//					Method getMethod = context.getClass().getMethod("get".concat(methodName));
//					Float oldValue = (Float) getMethod.invoke(context);
		    		Class<?>[] params = {float.class, boolean.class};
					Method setMethod = context.getClass().getMethod("set".concat(methodName), params);
					setMethod.invoke(context, (float)source.getValue(), false);
					//model.notifyAllViews();
					model.getElicoideModel().notifyAllViews();
					model.getTrunkModel().notifyAllViews();
					
				} catch (SecurityException e1) {
					e1.printStackTrace();
				} catch (NoSuchMethodException e1) {
					e1.printStackTrace();
				}catch (IllegalArgumentException e1) {
					e1.printStackTrace();
				} catch (IllegalAccessException e1) {
					e1.printStackTrace();
				} catch (InvocationTargetException e1) {
					e1.printStackTrace();
				}
			//}
		}
	}
}
